/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.warehouse3;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.WebServiceRef;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.manufacturers.Manufacturer1;
import org.manufacturers.Manufacturer1Service;
import org.manufacturers.Manufacturer2;
import org.manufacturers.Manufacturer2Service;
import org.manufacturers.Manufacturer3;
import org.manufacturers.Manufacturer3Service;
import org.manufacturers.Product;
import org.manufacturers.PurchaseOrder;

/**
 *
 * @author Pacho
 */
@WebService()
public class Warehouse3WS {
    @WebServiceRef(wsdlLocation = "WEB-INF/wsdl/client/Manufacturer1Service/localhost_8080/Manufacturers/Manufacturer1Service.wsdl")
    private Manufacturer1Service service;

    private static final String INVENTORY_FILE = "inventory.xml";
    private static int orderNumber = 0;
    private static final String LOG_FILE = "WH3log.txt";
    
    /**
     * Web service operation
     */
    @WebMethod(operationName = "shipGoods")
    public ItemShippingStatusList shipGoods(@WebParam(name = "itemList")
    java.util.ArrayList<Item> itemList, @WebParam(name = "info")
    Customer info)
    {

        ItemShippingStatusList issl = new ItemShippingStatusList();
        ArrayList<Item> shippedItems = new ArrayList<Item>();
        ArrayList<Item> notShippedItems = new ArrayList<Item>();


        //going through each item in the list and checking the inv to see if there is enough to send
        for(int j=0; j < itemList.size(); j++)
        {

            DocumentBuilderFactory docBuilderFactory = null;
            DocumentBuilder docBuilder = null;
            Document doc = null;

            try
            {

              docBuilderFactory = DocumentBuilderFactory.newInstance();
              docBuilder = docBuilderFactory.newDocumentBuilder();
              //doc = docBuilder.parse (new File("/Users/DJDocStrange/NetBeansProjects/Assign1Q4/web/WEB-INF/files/inventory.xml"));
              doc = docBuilder.parse (new File(Warehouse3WS.class.getResource(INVENTORY_FILE).toURI()));


            } catch (URISyntaxException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SAXException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            }



             NodeList allProducts = doc.getElementsByTagName("*");
             doc.getDocumentElement().normalize();


             int qtyonhand = -1;
             Attr qty = null;


            for (int i=0; i < allProducts.getLength(); i++)
            {
                Node node = allProducts.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element element = (Element) node;

                    if(element.getNodeName().equalsIgnoreCase("item-entry") && element.getAttribute("product-type").equalsIgnoreCase(itemList.get(j).getProductType()) && element.getAttribute("manufacturer-name").equalsIgnoreCase(itemList.get(j).getManufacturerName()))
                     {
                        qty = element.getAttributeNode("quantity");
                        qtyonhand = Integer.parseInt(element.getAttribute("quantity"));
                        break;
                    }
                }
            }

             int qtyRequired = itemList.get(j).getQuantity();

             //checking to see if there is enough to ship, then i ship it all.
             if(qtyRequired <= qtyonhand)
             {
                 //add to shipped items list
                 shippedItems.add(itemList.get(j));

                 //remove quantity from inventory.xml
                 int newQty = qtyonhand - qtyRequired;
                 qty.setValue(String.valueOf(newQty));

             }
             else if(qtyRequired > qtyonhand)
             {
                 int qtyLefttoShip = qtyRequired - qtyonhand;


                 //adding what i sent to the shipped list
                 Item itemtoship = new Item(itemList.get(j));
                 itemtoship.setQuantity(qtyonhand);
                 shippedItems.add(itemtoship);

                 //removing quantity from stock
                 int none = 0;
                 qty.setValue(String.valueOf(none));

                 //adding item to ship later list
                 Item itemtoshiplater = new Item(itemList.get(j));
                 itemtoshiplater.setQuantity(qtyLefttoShip);
                 notShippedItems.add(itemtoshiplater);


             }

                  //Writing to the file
                  try
                  {

                    TransformerFactory transformerFactory = TransformerFactory.newInstance();
                    Transformer transformer = transformerFactory.newTransformer();

                    DOMSource source = new DOMSource(doc);
                    //StreamResult result = new StreamResult(new File("/Users/DJDocStrange/NetBeansProjects/Assign1Q4/web/WEB-INF/files/inventory.xml"));
                    StreamResult result = new StreamResult(new File(Warehouse3WS.class.getResource(INVENTORY_FILE).toURI()));


                    transformer.transform(source, result);

                    //DEBUG
                    System.out.println("Inventory saved!");

            } catch (URISyntaxException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            } catch (TransformerException ex) {
                Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            }



        }

        //setting info for the itemshippingstatuslist which i return to the client
        issl.setCust(info);
        issl.setItemList(itemList);
        issl.setNotShippedItems(notShippedItems);
        issl.setShippedItems(shippedItems);

        //writing to the log file....
        String logInput = "==========\nShipped: ";

        for(int k = 0; k < shippedItems.size(); k++)
        {
            logInput += "\n" + shippedItems.get(k).getQuantity() + " of " + shippedItems.get(k).getProductType() + " From " + shippedItems.get(k).getManufacturerName();
        }

        logInput += "\nCustomer: " + info.getName() + " from " + info.getCity() + "\n==========";
        writeToLog(logInput);



        //replenishing the inventory
        replenish();

       return issl;
    }

     private void replenish()
    {

        int lowInv = 20;
        int reorder = 100;

        Manufacturer1Service manservice1 = new Manufacturer1Service();
        Manufacturer1 manserve1 = manservice1.getManufacturer1Port();

        Manufacturer2Service manservice2 = new Manufacturer2Service();
        Manufacturer2 manserve2 = manservice2.getManufacturer2Port();

        Manufacturer3Service manservice3 = new Manufacturer3Service();
        Manufacturer3 manserve3 = manservice3.getManufacturer3Port();

        
        //checking all products one by one and comparing onhand quantity to lowInv threshold. If its <= then i reorder
            DocumentBuilderFactory docBuilderFactory = null;
            DocumentBuilder docBuilder = null;
            Document doc = null;

            try
            {

              docBuilderFactory = DocumentBuilderFactory.newInstance();
              docBuilder = docBuilderFactory.newDocumentBuilder();
              //doc = docBuilder.parse (new File("/Users/DJDocStrange/NetBeansProjects/Assign1Q4/web/WEB-INF/files/inventory.xml"));
              doc = docBuilder.parse (new File(Warehouse3WS.class.getResource(INVENTORY_FILE).toURI()));

        } catch (URISyntaxException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        }



             NodeList allProducts = doc.getElementsByTagName("*");
             doc.getDocumentElement().normalize();


             int qtyonhand = -1;
             Attr qty = null;   
             String manu = null;
             String prod = null;


            for (int i=0; i < allProducts.getLength(); i++)
            {
                Node node = allProducts.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element element = (Element) node;

                    if(element.getNodeName().equalsIgnoreCase("item-entry"))
                    {
                        manu = element.getAttributeNode("manufacturer-name").getValue();
                        //System.out.println(manu);
                        prod = element.getAttributeNode("product-type").getValue();
                        //System.out.println(prod);
                        qty = element.getAttributeNode("quantity");
                        qtyonhand = Integer.parseInt(element.getAttribute("quantity"));

                        if(qtyonhand <= lowInv)
                        {
                            boolean makemore = false;
                            if (manu.equals("manufacturer1"))
                            {
                                //Creating the PO
                                //Product productforPO = manserve1.getProductInfo(prod);
                                Product productforPO = getProductInfoAsynch(prod, 1);
                                PurchaseOrder po = new PurchaseOrder();
                                po.setOrderNum("wh3reorder" + orderNumber);
                                po.setCustomerRef("wh3");
                                po.setProduct(productforPO);
                                po.setQuantity(reorder);
                                po.setUnitPrice(productforPO.getUnitPrice());
                                //  makemore = manserve1.processPurchaseOrder(po);
                                makemore = processPurchaseOrderAsynch(po, 1);

                                //writing to log
                                writeToLog("Replenishing inventory of " + productforPO.getProductType() + " from Manufacturer 1");
                            }
                            else if (manu.equals("manufacturer2"))
                            {
                                //Creating the PO
                                //Product productforPO = manserve2.getProductInfo(prod);
                                Product productforPO = getProductInfoAsynch(prod, 2);
                                PurchaseOrder po = new PurchaseOrder();
                                po.setOrderNum("wh3reorder" + orderNumber);
                                po.setCustomerRef("wh3");
                                po.setProduct(productforPO);
                                po.setQuantity(reorder);
                                po.setUnitPrice(productforPO.getUnitPrice());
                               // makemore = manserve2.processPurchaseOrder(po);
                                makemore = processPurchaseOrderAsynch(po, 2);

                                //writing to log
                                writeToLog("Replenishing inventory of " + productforPO.getProductType() + " from Manufacturer 2");
                            }
                            else if (manu.equals("manufacturer3"))
                            {
                                //Creating the PO
                                //Product productforPO = manserve3.getProductInfo(prod);
                                Product productforPO = getProductInfoAsynch(prod, 3);
                                PurchaseOrder po = new PurchaseOrder();
                                po.setOrderNum("wh3reorder" + orderNumber);
                                po.setCustomerRef("wh3");
                                po.setProduct(productforPO);
                                po.setQuantity(reorder);
                                po.setUnitPrice(productforPO.getUnitPrice());
                                //makemore = manserve3.processPurchaseOrder(po);
                                makemore = processPurchaseOrderAsynch(po, 3);

                                //writing to log
                                writeToLog("Replenishing inventory of " + productforPO.getProductType() + " from Manufacturer 3");
                            }
                            else
                            {
                                System.out.println("manufacturer doesnt match");
                            }

                            //check to see if the processPurchaseOrder call was successful
                            if (makemore == true)
                            {
                            int newQty = qtyonhand + reorder;
                            qty.setValue(String.valueOf(newQty));
                            System.out.println("Replenishment Successful!");
                            }
                            else
                            {
                                System.out.println("Error processing the order");
                            }
                            orderNumber++;
                        }

                    }
                }
            }


                  //Writing to the file
                  try
                  {

                    TransformerFactory transformerFactory = TransformerFactory.newInstance();
                    Transformer transformer = transformerFactory.newTransformer();

                    DOMSource source = new DOMSource(doc);
                    //StreamResult result = new StreamResult(new File("/Users/DJDocStrange/NetBeansProjects/Assign1Q4/web/WEB-INF/files/inventory.xml"));
                    StreamResult result = new StreamResult(new File(Warehouse3WS.class.getResource(INVENTORY_FILE).toURI()));


                    transformer.transform(source, result);

                    //DEBUG
                    System.out.println("Replenishment saved!");

        } catch (URISyntaxException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public boolean processPurchaseOrderAsynch(PurchaseOrder aPO, int manuType)
    {

        try
        {
            // Call Web Service Operation(async. callback)
            
            org.manufacturers.Manufacturer1Service service1 = new org.manufacturers.Manufacturer1Service();
            org.manufacturers.Manufacturer1 port1 = service1.getManufacturer1Port();

            org.manufacturers.Manufacturer2Service service2 = new org.manufacturers.Manufacturer2Service();
            org.manufacturers.Manufacturer2 port2 = service2.getManufacturer2Port();

            org.manufacturers.Manufacturer3Service service3 = new org.manufacturers.Manufacturer3Service();
            org.manufacturers.Manufacturer3 port3 = service3.getManufacturer3Port();


            
            // TODO initialize WS operation arguments here
            //org.manufacturers.PurchaseOrder aPO = new org.manufacturers.PurchaseOrder();

            javax.xml.ws.AsyncHandler<org.manufacturers.ProcessPurchaseOrderResponse> asyncHandler = new javax.xml.ws.AsyncHandler<org.manufacturers.ProcessPurchaseOrderResponse>()
            {
                public void handleResponse(javax.xml.ws.Response<org.manufacturers.ProcessPurchaseOrderResponse> response)
                {
                    try
                    {
                        // TODO process asynchronous response here
                        System.out.println("Result = "+  response.get());
                    }
                    catch(Exception ex)
                    {
                        // TODO handle exception
                    }
                }
            };


            java.util.concurrent.Future<? extends java.lang.Object> result = null;
            
            if( manuType == 1)
            {
                result = port1.processPurchaseOrderAsync(aPO, asyncHandler);
            }
            else if(manuType == 2)
            {
                result = port2.processPurchaseOrderAsync(aPO, asyncHandler);
            }
            else if(manuType == 3)
            {
                result = port3.processPurchaseOrderAsync(aPO, asyncHandler);
            }
            
            while(!result.isDone())
            {
                // do something
                System.out.println("++++++++++ Waiting for asynchronus reply (PurchaseOrder()! +++++++++++++\n\n");
                Thread.sleep(100);
            }

            System.out.println("++++++++++ Asynchronus op complete (PurchaseOrder() +++++++++++++\n\n");
            return ((org.manufacturers.ProcessPurchaseOrderResponse) result.get()).isReturn();
        }
        catch (Exception ex)
        {
            // TODO handle custom exceptions here
        }

        return true;
    }

    public Product getProductInfoAsynch(String aProdName, int manuType)
    {
        Product prod = null;


        try
        {
            // Call Web Service Operation(async. callback)
            org.manufacturers.Manufacturer1Service service1 = new org.manufacturers.Manufacturer1Service();
            org.manufacturers.Manufacturer1 port1 = service1.getManufacturer1Port();

            org.manufacturers.Manufacturer2Service service2 = new org.manufacturers.Manufacturer2Service();
            org.manufacturers.Manufacturer2 port2 = service2.getManufacturer2Port();

            org.manufacturers.Manufacturer3Service service3 = new org.manufacturers.Manufacturer3Service();
            org.manufacturers.Manufacturer3 port3 = service3.getManufacturer3Port();

     

            javax.xml.ws.AsyncHandler<org.manufacturers.GetProductInfoResponse> asyncHandler = new javax.xml.ws.AsyncHandler<org.manufacturers.GetProductInfoResponse>()
            {
                public void handleResponse(javax.xml.ws.Response<org.manufacturers.GetProductInfoResponse> response)
                {
                    try
                    {
                        // TODO process asynchronous response here
                        System.out.println("Result = "+ response.get().getClass().getSimpleName());
                        //Product prod = response.get().getReturn();
                        //System.out.println("Prod = "+ prod.getManufacturerName() + " " + prod.getProductType());
                    }
                    catch(Exception ex) {
                        // TODO handle exception
                    }
                }
            };

            java.util.concurrent.Future<? extends java.lang.Object> result = null;

            if( manuType == 1)
            {
                result = port1.getProductInfoAsync(aProdName, asyncHandler);
            }
            else if(manuType == 2)
            {
                result = port2.getProductInfoAsync(aProdName, asyncHandler);
            }
            else if(manuType == 3)
            {
                result = port3.getProductInfoAsync(aProdName, asyncHandler);
            }

            while(!result.isDone())
            {
                // do something
                System.out.println("++++++++++ Waiting for asynchronus reply (getProductInfo()! +++++++++++++\n\n");
                Thread.sleep(100);
            }

            System.out.println("++++++++++ Asynchronus op complete (getProductInfo() +++++++++++++\n\n");

            prod = ((org.manufacturers.GetProductInfoResponse) result.get()).getReturn();
            System.out.println("Prod = "+ prod.getManufacturerName() + " " + prod.getProductType());

        } 
        catch (Exception ex)
        {
            // TODO handle custom exceptions here
        }

        return prod;
    }

    /**
     * Web service operation
     */
    @WebMethod(operationName = "getCatalog")
    public java.util.ArrayList<Item> getCatalog() {

        ArrayList<Item> itemList = new ArrayList<Item>();

        DocumentBuilderFactory docBuilderFactory = null;
        DocumentBuilder docBuilder = null;
        Document doc = null;

        try
        {

          docBuilderFactory = DocumentBuilderFactory.newInstance();
          docBuilder = docBuilderFactory.newDocumentBuilder();
          //doc = docBuilder.parse (new File("/Users/DJDocStrange/NetBeansProjects/Assign1Q4/web/WEB-INF/files/inventory.xml"));
          doc = docBuilder.parse (new File(Warehouse3WS.class.getResource(INVENTORY_FILE).toURI()));

        } catch (URISyntaxException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        }

        NodeList allProducts = doc.getElementsByTagName("*");
        doc.getDocumentElement().normalize();


        for (int i=0; i < allProducts.getLength(); i++)
        {
            Node node = allProducts.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE)
            {
                Element element = (Element) node;

                if(element.getNodeName().equalsIgnoreCase("item-entry"))
                {
                    Item item = new Item();

                    item.setManufacturerName( element.getAttributeNode("manufacturer-name").getValue() );
                    item.setProductType( element.getAttributeNode("product-type").getValue() );
                    item.setQuantity( Integer.parseInt(element.getAttribute("quantity")) );
                    item.setUnitPrice( Float.parseFloat(element.getAttribute("unit-price")) );

                    itemList.add(item);
                }
            }

        }

        return itemList;
    }


    
    private boolean writeToLog(String input)
    {

        PrintWriter outputStream = null;
        String folder = "";

        try {

            folder = Warehouse3WS.class.getResource(INVENTORY_FILE).toURI().toString();
            folder = folder.substring(5, folder.length()-13);
            outputStream = new PrintWriter(new FileOutputStream(folder + LOG_FILE, true));


        } catch (FileNotFoundException ex) {
           // Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Error writing to the log file for WH 3");
        } catch (URISyntaxException ex) {
            Logger.getLogger(Warehouse3WS.class.getName()).log(Level.SEVERE, null, ex);
        }

        System.out.println("Writing to log file for Warehouse 3...");

        outputStream.println(input);
        outputStream.close();

        System.out.println("Finished writing...");

        return true;


    }


}
